using System;
using NUnit.Framework;



namespace ValidationFramework.Specifications.Tests
{
    public sealed class HasLengthInRangeSpecTests
    {

        const int expectedMinimum = 1;
        const int expectedMaximum = 3;

        [TestFixture]
        public sealed class Construction
        {
            [Test]
			public void Should_Set_Properties_Correctly()
            {
                var validator = new HasLengthInRangeSpec(expectedMinimum, expectedMaximum, false);
                Assert.AreEqual(expectedMinimum, validator.Minimum);
                Assert.AreEqual(expectedMinimum, validator.Minimum);
                Assert.IsFalse(validator.TrimWhiteSpace);
            }


            [Test]
            public void Should_Default_TrimWhiteSpace_To_True()
            {
                var validator = new HasLengthInRangeSpec(expectedMinimum, expectedMaximum);
                Assert.AreEqual(expectedMinimum, validator.Minimum);
				Assert.AreEqual(expectedMaximum, validator.Maximum);
                Assert.IsTrue(validator.TrimWhiteSpace);
            }

            [Test]
		   public void Should_Allow_Equal_Min_And_Max()
            {
                new HasLengthInRangeSpec(1, 1);
            }


            [Test]
            [ExpectedException(typeof(ArgumentException), ExpectedMessage = "Minimum must be less than or equal to Maximum.\r\nParameter name: minimum")]
            public void Should_Thow_Exception_When_Minimum_Greater_Than_Maximum()
            {
                new HasLengthInRangeSpec(2, 1);
            }


            [Test]
            [ExpectedException(typeof(ArgumentException), ExpectedMessage = "Minimum must be greater than 0.\r\nParameter name: minimum")]
			public void Should_Thow_Exception_When_Minimum_Less_Than_Zero()
            {
                new HasLengthInRangeSpec(-1, 1);
            }
        }
        [TestFixture]
        public sealed class Equality
        {
            [Test]
            public void Simple()
            {
                var validator1 = new HasLengthInRangeSpec(10, 15, true);
                var validator2 = new HasLengthInRangeSpec(10, 15, true);
                Assert.IsTrue(validator1.IsEquivalentTo(validator2));
            }
        }

        [TestFixture]
        public sealed class Validate
        {

            [Test]
            public void TrimWhiteSpace()
            {
                var validator = new HasLengthInRangeSpec(expectedMinimum, expectedMaximum, true);
                Assert.IsTrue(validator.IsSatisfiedBy(null));
                Assert.IsFalse(validator.IsSatisfiedBy(""));
                Assert.IsFalse(validator.IsSatisfiedBy(" "));
                Assert.IsTrue(validator.IsSatisfiedBy("a"));
                Assert.IsTrue(validator.IsSatisfiedBy(" a "));
                Assert.IsTrue(validator.IsSatisfiedBy("aa"));
                Assert.IsTrue(validator.IsSatisfiedBy(" aa "));
                Assert.IsTrue(validator.IsSatisfiedBy("aaa"));
                Assert.IsTrue(validator.IsSatisfiedBy(" aaa "));
                Assert.IsFalse(validator.IsSatisfiedBy("aaaa"));
                Assert.IsFalse(validator.IsSatisfiedBy(" aaaa "));
            }



            [Test]
            public void NoTrimWhiteSpace()
            {
                var validator = new HasLengthInRangeSpec(expectedMinimum, expectedMaximum, false);
                Assert.IsTrue(validator.IsSatisfiedBy(null));
                Assert.IsFalse(validator.IsSatisfiedBy(""));
                Assert.IsTrue(validator.IsSatisfiedBy(" "));
                Assert.IsTrue(validator.IsSatisfiedBy("a"));
                Assert.IsTrue(validator.IsSatisfiedBy(" a "));
                Assert.IsTrue(validator.IsSatisfiedBy("aa"));
                Assert.IsFalse(validator.IsSatisfiedBy(" aa "));
                Assert.IsTrue(validator.IsSatisfiedBy("aaa"));
                Assert.IsFalse(validator.IsSatisfiedBy(" aaa "));
                Assert.IsFalse(validator.IsSatisfiedBy("aaaa"));
                Assert.IsFalse(validator.IsSatisfiedBy(" aaaa "));
            }

            [Test]
            public void EqualMinAndMax()
            {
                var validator = new HasLengthInRangeSpec(2, 2, true);
                Assert.IsFalse(validator.IsSatisfiedBy(""));
                Assert.IsFalse(validator.IsSatisfiedBy(" "));
                Assert.IsFalse(validator.IsSatisfiedBy("a"));
                Assert.IsFalse(validator.IsSatisfiedBy("a "));
                Assert.IsTrue(validator.IsSatisfiedBy("aa"));
                Assert.IsTrue(validator.IsSatisfiedBy("aa "));
                Assert.IsFalse(validator.IsSatisfiedBy("aaa"));
                Assert.IsFalse(validator.IsSatisfiedBy("aaa "));
            }
        }

        [TestFixture]
        public sealed class CheckTypes
        {

            [Test]
            public void Can_Be_Applied_To_String()
            {
                var validator = new HasLengthInRangeSpec(expectedMinimum, expectedMaximum, true);
                Assert.IsTrue(validator.CanBeSatisfiedBy(typeof(string)));
            }


            [Test]
            //[ExpectedException(typeof(ArgumentException), ExpectedMessage = "Member 'foo' must be a 'System.String' to be used for the ValidationFramework.LengthStringRule. Actual Type 'System.Int32'.\r\nParameter name: value")]
            public void ExceptionInvalidType()
            {
                var validator = new HasLengthInRangeSpec(expectedMinimum, expectedMaximum, true);
                Assert.IsFalse(validator.CanBeSatisfiedBy(typeof(int)));
            }
        }


    }
}